package com.lishe.lishe.net;

import android.support.annotation.NonNull;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.lishe.lishe.lishe.utils.LoadingUtils;
import com.lishe.lishe.lishe.utils.LogUtil;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

/**
 * Created by Bin
 */

public abstract class BaseHttpLoader {

    private String mUrl;
    private Retrofit mRetrofit;
    private Class<? extends BaseProtocal> mProtocalClass;

    public BaseHttpLoader(Class<? extends BaseProtocal> protocalClass, String url) {
        this.mUrl = url;
        this.mProtocalClass = protocalClass;
        mRetrofit = buildRetrofit();
    }

    /**
     * url
     * APP使用：Globals.LISHE_URL
     * 一企一舍：Globals.LISHE_URL_EXCITATION
     */
    private Retrofit buildRetrofit() {
        return new Retrofit.Builder()
                .baseUrl(mUrl)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(genericClient())
//                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }

    private OkHttpClient genericClient() {
        return OkhttpCreateHelper.getOkHttpClient();
    }

    public abstract Observable<ResponseBody> structureObservable(NetAPI netAPI);  //拿到具体的Observable,让子类实现

    public void executor(final ResultListener mResultListener) {
        Observable<ResponseBody> observable = structureObservable(mRetrofit.create(NetAPI.class));
        LogUtil.w(mUrl);
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread()) //定义主线程中执行
                .subscribe(new Observer<ResponseBody>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(ResponseBody responseBody) {
                        dispatchResult(responseBody, mResultListener);
                        LoadingUtils.closeDialog();
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        mResultListener.onError(e);
                        LoadingUtils.closeDialog();
                    }

                    @Override
                    public void onComplete() {
                    }
                });
    }

    private void dispatchResult(ResponseBody mResponseBody, @NonNull ResultListener mResultListener) {
        String result = convertStreamToString(mResponseBody.byteStream());
        Gson gson = new Gson();
        LogUtil.completeLog(mProtocalClass.getSimpleName() + "完整返回数据", result);
        try {
            BaseProtocal baseProtocal = gson.fromJson(result, mProtocalClass);
            if (baseProtocal.errcode == 0) {
                mResultListener.onSuccess(baseProtocal);
            } else {
                mResultListener.onFail(baseProtocal.errcode, baseProtocal.msg);
            }
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            mResultListener.onFail(300, "数据异常");
        }
    }

    /**
     * 将输入流转成字符串
     *
     * @param is 输入流
     * @return 返回字符串
     */
    public static String convertStreamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

}
